const express = require('express')
// 使用fs-extra第三方模块处理文件操作
const fse = require('fs-extra')
const path = require('path')
const fs = require('fs');
// // 创建存储目录
const storageDir = 'uploadFiles/';
if (!fs.existsSync(storageDir)) {
    fs.mkdirSync(storageDir);
}

const app = express()
// 设置允许跨域
const cors = require('cors');
app.use(cors())
// 静态资源托管
app.use(express.static('static'))
// 导入中间件body-parser解析请求体
const bodyParser = require('body-parser')
// 使用中间件
// 处理URL编码格式的数据
app.use(bodyParser.urlencoded({ extended: false }));
// 处理JSON格式的数据
app.use(bodyParser.json());

// app.post('/upload', (req, res) => {
//     res.send({
//         msg: '上传成功',
//         success: true
//     })
// })

// 使用multer中间件处理上传文件
const multer = require('multer')
const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        // 设置uploadFiles文件夹为文件存储路径
        // cb(null, './uploadFiles');
        cb(null, storageDir); // 存储目录
    },
});
const upload = multer({storage})

// app.post('/upload', upload.single('file'), (req, res) => {
//     setTimeout(()=>{
//         res.send({
//             msg: 'File uploaded successfully!'
//         });
//     },1000*Math.random())
// })

// 上传接口及保存上传内容
app.post('/upload', upload.single('file'), (req, res) => {
    // 使用一个文件Hash值同名的文件夹保存所有切片
    const { fileHash, chunkIndex } = req.body;
    // 上传文件临时目录文件夹
    let tempFileDir = path.resolve('uploadFiles', fileHash);
    // 如果当前文件的临时文件夹不存在，则创建该文件夹
    if (!fse.pathExistsSync(tempFileDir)) {
        fse.mkdirSync(tempFileDir)
    }
    
    // 目标切片位置
    const tempChunkPath = path.resolve(tempFileDir, chunkIndex);
    // 当前切片位置（multer默认保存的位置）
    // req.file 是由 multer 中间件处理上传文件后得到的对象，其中包含了有关上传文件的信息。req.file.path 表示上传文件的临时存储路径。
    let currentChunkPath = path.resolve(req.file.path);
    console.log('----->',currentChunkPath)

    // 如果无临时文件夹或不存在该切片，则将用户上传的切片移到临时文件夹里
    // 如果有临时文件夹并存在该切片，则删除用户上传的切片（因为用不到了）
    // fse.existsSync(tempChunkPath) 是用于检查指定路径下的文件或目录是否存在的方法。
    if (!fse.existsSync(tempChunkPath)) {
        fse.moveSync(currentChunkPath, tempChunkPath)
    } else {
        fse.removeSync(currentChunkPath)
    }

    setTimeout(() => {
        res.send({
            msg: '上传成功',
            success: true
        })
    }, 1000 * Math.random())
})

// 合并接口
app.get('/merge', async (req, res) => {
    const { fileHash, fileName } = req.query;
    // 最终合并的文件路径
    // path.extname(fileName)获取扩展名即.mp3
    const filePath = path.resolve('uploadFiles', fileHash + path.extname(fileName));

    // 临时文件夹路径
    let tempFileDir = path.resolve('uploadFiles', fileHash);

    // 读取临时文件夹，获取所有切片
    const chunkPaths = fse.readdirSync(tempFileDir);

    // ['0','1','2','3','4']
    // console.log('chunkPaths：', chunkPaths);

    // 将切片追加到文件中
    let mergeTasks = [];
    for (let index = 0; index < chunkPaths.length; index++) {
        mergeTasks.push(new Promise((resolve) => {
            // 当前遍历的切片路径
            const chunkPath = path.resolve(tempFileDir, index + '');
            // 将当前遍历的切片切片追加到文件中
            fse.appendFileSync(filePath, fse.readFileSync(chunkPath));
            // 删除当前遍历的切片
            // fse.unlinkSync(chunkPath)： 用于删除指定路径下的文件。如果 chunkPath 对应的是一个文件而非目录，这个方法会删除该文件。如果 chunkPath 是一个目录路径，则删除操作会失败。
            fse.unlinkSync(chunkPath);
            resolve();
        }))
    }
    await Promise.all(mergeTasks);
    // 等待所有切片追加到文件后，删除临时文件夹
    // fse.removeSync(tempFileDir)： 用于删除整个目录及其所有内容，包括目录内的文件和子目录。这个方法会递归地删除目录下的所有文件和子目录。
    fse.removeSync(tempFileDir);
    res.send({
        msg: "合并成功",
        success: true
    });
})


// 校验接口，校验是否已经存在目标文件
app.get('/verify', (req, res) => {
    const { fileHash, fileName } = req.query;
    const filePath = path.resolve('uploadFiles', fileHash + path.extname(fileName));
    const exitFile = fse.pathExistsSync(filePath);
    res.send({
        exitFile
    })
})



app.listen(3000, () => {
    console.log('服务已运行：http://localhost:3000');
})
